bitkeeper revision 1.1108.24.2 (4108d1f8mh1HwCuBJAKjn8UuBU4wTA)
authormjw@wray-m-3.hpl.hp.com <mjw@wray-m-3.hpl.hp.com>
Thu, 29 Jul 2004 10:31:20 +0000 (10:31 +0000)
committermjw@wray-m-3.hpl.hp.com <mjw@wray-m-3.hpl.hp.com>
Thu, 29 Jul 2004 10:31:20 +0000 (10:31 +0000)
Change to supporting reference to domain by name or id and
make xm tools use names.

12 files changed:
tools/python/xen/xend/XendDomain.py
tools/python/xen/xend/XendDomainInfo.py
tools/python/xen/xend/server/SrvDomain.py
tools/python/xen/xend/server/SrvDomainDir.py
tools/python/xen/xend/server/blkif.py
tools/python/xen/xend/server/controller.py
tools/python/xen/xend/server/netif.py
tools/python/xen/xend/sxp.py
tools/python/xen/xm/create.py
tools/python/xen/xm/destroy.py
tools/python/xen/xm/main.py
tools/python/xen/xm/shutdown.py

index 1e6a91a24432d195123b959c75b796d6b62bae12..3a07b49294c5591234809a703b0dbc71b9524bc9 100644 (file)
@@ -39,15 +39,23 @@ class XendDomain:
     dbpath = "domain"
 
     """Table of domain info indexed by domain id."""
-    domain = {}
+    domain_by_id = {}
+    domain_by_name = {}
     
     """Table of domains to restart, indexed by domain id."""
-    restarts = {}
+    restarts_by_id = {}
+    restarts_by_name = {}
 
     """Table of delayed calls."""
     schedule = {}
     
     def __init__(self):
+        # Hack alert. Python does not support mutual imports, but XendDomainInfo
+        # needs access to the XendDomain instance to look up domains. Attempting
+        # to import XendDomain from XendDomainInfo causes unbounded recursion.
+        # So we stuff the XendDomain instance (self) into XendDomainInfo's
+        # namespace as 'xd'.
+        XendDomainInfo.xd = self
         # Table of domain info indexed by domain id.
         self.db = XendDB.XendDB(self.dbpath)
         self.domain_db = self.db.fetchall("")
@@ -173,7 +181,8 @@ class XendDomain:
         @return: deferred
         """
         def cbok(dominfo):
-            self.domain[dominfo.id] = dominfo
+            self.domain_by_id[dominfo.id] = dominfo
+            self.domain_by_name[dominfo.name] = dominfo
             if dominfo.restart_pending():
                 self.domain_restart_add(dominfo)
         
@@ -181,17 +190,17 @@ class XendDomain:
         deferred.addCallback(cbok)
         return deferred
 
-    def _add_domain(self, id, info, notify=1):
+    def _add_domain(self, info, notify=1):
         """Add a domain entry to the tables.
 
-        @param id:     domain id
         @param info:   domain info object
         @param notify: send a domain created event if true
         """
-        self.domain[id] = info
-        self.domain_db[id] = info.sxpr()
-        self.sync_domain(id)
-        if notify: eserver.inject('xend.domain.created', id)
+        self.domain_by_id[info.id] = info
+        self.domain_db[info.id] = info.sxpr()
+        self.domain_by_name[info.name] = info
+        self.sync_domain(info.id)
+        if notify: eserver.inject('xend.domain.created', info.name)
 
     def _delete_domain(self, id, notify=1):
         """Remove a domain from the tables.
@@ -199,9 +208,12 @@ class XendDomain:
         @param id:     domain id
         @param notify: send a domain died event if true
         """
-        if id in self.domain:
-            if notify: eserver.inject('xend.domain.died', id)
-            del self.domain[id]
+        if id in self.domain_by_id:
+            info = self.domain_by_id[id]
+            if notify: eserver.inject('xend.domain.died', info.name)
+            if info.name in self.domain_by_name:
+                del self.domain_by_name[info.name]
+            del self.domain_by_id[id]
         if id in self.domain_db:
             del self.domain_db[id]
             self.db.delete(id)
@@ -229,7 +241,7 @@ class XendDomain:
                 if reason in ['poweroff', 'reboot']:
                     self.domain_restart_schedule(id, reason)
             self.final_domain_destroy(id)
-        if len(self.restarts):
+        if self.domain_restarts_exist():
             self.domain_restarts_schedule()
 
     def refresh(self):
@@ -243,14 +255,14 @@ class XendDomain:
         for d in domlist:
             id = str(d['dom'])
             doms[id] = d
-            if id not in self.domain:
+            if id not in self.domain_by_id:
                 savedinfo = None
                 deferred = XendDomainInfo.vm_recreate(savedinfo, d)
                 def cbok(dominfo):
-                    self._add_domain(dominfo.id, dominfo)
+                    self._add_domain(dominfo)
                 deferred.addCallback(cbok)
         # Remove entries for domains that no longer exist.
-        for d in self.domain.values():
+        for d in self.domain_by_id.values():
             info = doms.get(d.id)
             if info:
                 d.update(info)
@@ -263,7 +275,7 @@ class XendDomain:
 
         @param id: domain id
         """
-        dominfo = self.domain.get(id)
+        dominfo = self.domain_by_id.get(id)
         if dominfo:
             self.domain_db[id] = dominfo.sxpr()
             self.sync_domain(id)
@@ -283,17 +295,25 @@ class XendDomain:
                 raise
                 pass
         else:
-            d = self.domain.get(id)
+            d = self.domain_by_id.get(id)
             if d:
                 d.update(dominfo[0])
 
     def domain_ls(self):
+        """Get list of domain names.
+
+        @return: domain names
+        """
+        self.refresh()
+        return self.domain_by_name.keys()
+
+    def domain_ls_ids(self):
         """Get list of domain ids.
 
-        @return: domain ids
+        @return: domain names
         """
         self.refresh()
-        return self.domain.keys()
+        return self.domain_by_id.keys()
 
     def domains(self):
         """Get list of domain objects.
@@ -301,7 +321,7 @@ class XendDomain:
         @return: domain objects
         """
         self.refresh()
-        return self.domain.values()
+        return self.domain_by_id.values()
     
     def domain_create(self, config):
         """Create a domain from a configuration.
@@ -310,7 +330,7 @@ class XendDomain:
         @return: deferred
         """
         def cbok(dominfo):
-            self._add_domain(dominfo.id, dominfo)
+            self._add_domain(dominfo)
             return dominfo
         deferred = XendDomainInfo.vm_create(config)
         deferred.addCallback(cbok)
@@ -323,7 +343,7 @@ class XendDomain:
         @return: deferred
         """
         def cbok(dominfo):
-            self._add_domain(dominfo.id, dominfo)
+            self._add_domain(dominfo)
             return dominfo
         log.info("Restarting domain: id=%s name=%s", dominfo.id, dominfo.name)
         deferred = dominfo.restart()
@@ -338,15 +358,14 @@ class XendDomain:
         @param config: configuration
         @return: deferred
         """
-        log.debug('domain_configure> id=%s config=%s', id, str(config))
-        dom = int(id)
-        dominfo = self.domain_get(dom)
+        dominfo = self.domain_get(id)
         if not dominfo:
             raise XendError("Invalid domain: " + str(id))
+        log.debug('domain_configure> id=%s config=%s', id, str(config))
         if dominfo.config:
-            raise XendError("Domain already configured: " + str(id))
+            raise XendError("Domain already configured: " + dominfo.name)
         def cbok(dominfo):
-            self._add_domain(dominfo.id, dominfo)
+            self._add_domain(dominfo)
             return dominfo
         deferred = dominfo.construct(config)
         deferred.addCallback(cbok)
@@ -361,7 +380,7 @@ class XendDomain:
         """
         
         def cbok(dominfo):
-            self._add_domain(dominfo.id, dominfo)
+            self._add_domain(dominfo)
             return dominfo
         deferred = XendDomainInfo.vm_restore(src, progress=progress)
         deferred.addCallback(cbok)
@@ -375,25 +394,39 @@ class XendDomain:
         """
         id = str(id)
         self.refresh_domain(id)
-        return self.domain.get(id)
-    
+        return self.domain_by_id.get(id)
+
+    def domain_lookup(self, name):
+        name = str(name)
+        dominfo = self.domain_by_name.get(name) or self.domain_by_id.get(name)
+        if dominfo:
+            return dominfo
+        raise XendError('invalid domain:' + name)
+
+    def domain_exists(self, name):
+        name = str(name)
+        if self.domain_by_name.get(name) or self.domain_by_id.get(name):
+            return 1
+        else:
+            return 0
+
     def domain_unpause(self, id):
         """Unpause domain execution.
 
         @param id: domain id
         """
-        dom = int(id)
-        eserver.inject('xend.domain.unpause', id)
-        return xc.domain_unpause(dom=dom)
+        dominfo = self.domain_lookup(id)
+        eserver.inject('xend.domain.unpause', dominfo.name)
+        return xc.domain_unpause(dom=dominfo.dom)
     
     def domain_pause(self, id):
         """Pause domain execution.
 
         @param id: domain id
         """
-        dom = int(id)
-        eserver.inject('xend.domain.pause', id)
-        return xc.domain_pause(dom=dom)
+        dominfo = self.domain_lookup(id)
+        eserver.inject('xend.domain.pause', dominfo.name)
+        return xc.domain_pause(dom=dominfo.dom)
     
     def domain_shutdown(self, id, reason='poweroff'):
         """Shutdown domain (nicely).
@@ -406,18 +439,15 @@ class XendDomain:
         @param id:     domain id
         @param reason: shutdown type: poweroff, reboot, suspend, halt
         """
-        dom = int(id)
-        id = str(id)
-        if dom <= 0:
-            return 0
+        dominfo = self.domain_lookup(id)
         if reason == 'halt':
-            self.domain_restart_cancel(id)
+            self.domain_restart_cancel(dominfo.id)
         else:
-            self.domain_restart_schedule(id, reason, force=1)
-        eserver.inject('xend.domain.shutdown', [id, reason])
+            self.domain_restart_schedule(dominfo.id, reason, force=1)
+        eserver.inject('xend.domain.shutdown', [dominfo.name, reason])
         if reason == 'halt':
             reason = 'poweroff'
-        val = xend.domain_shutdown(dom, reason)
+        val = xend.domain_shutdown(dominfo.id, reason)
         self.refresh_schedule()
         return val
 
@@ -428,10 +458,10 @@ class XendDomain:
         @param reason: shutdown reason
         """
         log.debug('domain_restart_schedule> %s %s %d', id, reason, force)
-        dominfo = self.domain.get(id)
+        dominfo = self.domain_lookup(id)
         if not dominfo:
             return
-        if id in self.restarts:
+        if dominfo.id in self.restarts_by_id:
             return
         restart = (force and reason == 'reboot') or dominfo.restart_needed(reason)
         if restart:
@@ -439,8 +469,9 @@ class XendDomain:
             self.domain_restart_add(dominfo)
 
     def domain_restart_add(self, dominfo):
-        self.restarts[dominfo.id] = dominfo
-        log.info('Scheduling restart for domain: id=%s name=%s', dominfo.id, dominfo.name)
+        self.restarts_by_name[dominfo.name] = dominfo
+        self.restarts_by_id[dominfo.id] = dominfo
+        log.info('Scheduling restart for domain: name=%s id=%s', dominfo.name, dominfo.id)
         self.domain_restarts_schedule()
             
     def domain_restart_cancel(self, id):
@@ -448,53 +479,57 @@ class XendDomain:
 
         @param id: domain id
         """
-        dominfo = self.restarts.get(id)
+        dominfo = self.restarts_by_id.get(id) or self.restarts_by_name.get(id)
         if dominfo:
-            log.info('Cancelling restart for domain: id=%s name=%s', dominfo.id, dominfo.name)
+            log.info('Cancelling restart for domain: name=%s id=%s', dominfo.name, dominfo.id)
             dominfo.restart_cancel()
-            del self.restarts[id]
+            del self.restarts_by_id[dominfo.id]
+            del self.restarts_by_name[dominfo.name]
 
     def domain_restarts(self):
         """Execute any scheduled domain restarts for domains that have gone.
         """
         self.domain_restarts_cancel()
-        for id in self.restarts.keys():
-            if id in self.domain:
+        for dominfo in self.restarts_by_id.values():
+            if dominfo.id in self.domain_by_id:
                 # Don't execute restart for domains still running.
                 continue
-            dominfo = self.restarts[id]
             # Remove it from the restarts.
-            del self.restarts[id]
+            del self.restarts_by_id[dominfo.id]
+            del self.restarts_by_name[dominfo.name]
             try:
                 def cbok(dominfo):
-                    log.info('Restarted domain id=%s as %s', id, dominfo.id)
+                    log.info('Restarted domain name=%s id=%s', dominfo.name, dominfo.id)
                     self.domain_unpause(dominfo.id)
                 def cberr(err):
-                    log.exception("Delayed exception restarting domain: id=%s", id)
+                    log.exception("Delayed exception restarting domain: name=%s id=%s",
+                                  dominfo.name, dominfo.id)
                 deferred = self.domain_restart(dominfo)
                 deferred.addCallback(cbok)
                 deferred.addErrback(cberr)
             except:
-                log.exception("Exception restarting domain: id=%s", id)
-        if len(self.restarts):
+                log.exception("Exception restarting domain: name=%s id=%s",
+                              dominfo.name, dominfo.id)
+        if self.domain_restarts_exist():
             # Run again later if any restarts remain.
             self.refresh_schedule(delay=5)
+
+    def domain_restarts_exist(self):
+        return len(self.restarts_by_id)
         
     def final_domain_destroy(self, id):
         """Final destruction of a domain..
 
         @param id: domain id
         """
-        dom = int(id)
-        if dom <= 0:
-            return 0
-        log.info('Destroying domain: id=%s', str(id))
-        eserver.inject('xend.domain.destroy', id)
-        dominfo = self.domain.get(id)
+        dominfo = self.domain_lookup(id)
+        log.info('Destroying domain: name=%s', dominfo.name)
+        eserver.inject('xend.domain.destroy', dominfo.name)
         if dominfo:
             val = dominfo.destroy()
         else:
-            val = xc.domain_destroy(dom=dom)
+            #todo
+            val = xc.domain_destroy(dom=dominfo.dom)
         return val       
 
     def domain_destroy(self, id, reason='halt'):
@@ -504,7 +539,6 @@ class XendDomain:
 
         @param id: domain id
         """
-        id = str(id)
         if reason == 'halt':
             self.domain_restart_cancel(id)
         elif reason == 'reboot':
@@ -522,9 +556,9 @@ class XendDomain:
         # Need a cancel too?
         # Don't forget to cancel restart for it.
         print 'domain_migrate>', id, dst
-        dom = int(id)
+        dominfo = self.domain_lookup(id)
         xmigrate = XendMigrate.instance()
-        val = xmigrate.migrate_begin(dom, dst)
+        val = xmigrate.migrate_begin(dominfo.id, dst)
         print 'domain_migrate<', val
         return val
 
@@ -536,9 +570,9 @@ class XendDomain:
         @param progress: output progress if true
         @return: deferred
         """
-        dom = int(id)
+        dominfo = self.domain_lookup(id)
         xmigrate = XendMigrate.instance()
-        return xmigrate.save_begin(dom, dst)
+        return xmigrate.save_begin(dominfo.id, dst)
     
     def domain_pincpu(self, dom, cpu):
         """Pin a domain to a cpu.
@@ -546,156 +580,149 @@ class XendDomain:
         @param dom: domain
         @param cpu: cpu number
         """
-        dom = int(dom)
-        return xc.domain_pincpu(dom, cpu)
+        dominfo = self.domain_lookup(id)
+        return xc.domain_pincpu(itn(dominfo.id), cpu)
 
-    def domain_cpu_bvt_set(self, dom, mcuadv, warp, warpl, warpu):
+    def domain_cpu_bvt_set(self, id, mcuadv, warp, warpl, warpu):
         """Set BVT (Borrowed Virtual Time) scheduler parameters for a domain.
         """
-        dom = int(dom)
-        return xc.bvtsched_domain_set(dom=dom, mcuadv=mcuadv,
+        dominfo = self.domain_lookup(id)
+        return xc.bvtsched_domain_set(dom=dominfo.dom, mcuadv=mcuadv,
                                       warp=warp, warpl=warpl, warpu=warpu)
 
-    def domain_cpu_bvt_get(self, dom):
+    def domain_cpu_bvt_get(self, id):
         """Get BVT (Borrowed Virtual Time) scheduler parameters for a domain.
         """
-        dom = int(dom)
-        return xc.bvtsched_domain_get(dom)
+        dominfo = self.domain_lookup(id)
+        return xc.bvtsched_domain_get(dominfo.dom)
     
-    def domain_cpu_fbvt_set(self, dom, mcuadv, warp, warpl, warpu):
+    def domain_cpu_fbvt_set(self, id, mcuadv, warp, warpl, warpu):
         """Set FBVT (Fair Borrowed Virtual Time) scheduler parameters for a domain.
         """
-        dom = int(dom)
-        return xc.fbvtsched_domain_set(dom=dom, mcuadv=mcuadv,
+        dominfo = self.domain_lookup(id)
+        return xc.fbvtsched_domain_set(dom=dominfo.dom, mcuadv=mcuadv,
                                        warp=warp, warpl=warpl, warpu=warpu)
 
-    def domain_cpu_fbvt_get(self, dom):
+    def domain_cpu_fbvt_get(self, id):
         """Get FBVT (Fair Borrowed Virtual Time) scheduler parameters for a domain.
         """
-        dom = int(dom)
-        return xc.fbvtsched_domain_get(dom)
+        dominfo = self.domain_lookup(id)
+        return xc.fbvtsched_domain_get(dominfo.dom)
         
-    def domain_cpu_atropos_set(self, dom, period, slice, latency, xtratime):
+    def domain_cpu_atropos_set(self, id, period, slice, latency, xtratime):
         """Set Atropos scheduler parameters for a domain.
         """
-        dom = int(dom)
-        return xc.atropos_domain_set(dom, period, slice, latency, xtratime)
+        dominfo = self.domain_lookup(id)
+        return xc.atropos_domain_set(dominfo.dom, period, slice, latency, xtratime)
 
-    def domain_cpu_atropos_get(self, dom):
+    def domain_cpu_atropos_get(self, id):
         """Get Atropos scheduler parameters for a domain.
         """
-        dom = int(dom)
-        return xc.atropos_domain_get(dom)
+        dominfo = self.domain_lookup(id)
+        return xc.atropos_domain_get(dominfo.dom)
 
-    def domain_device_create(self, dom, devconfig):
+    def domain_device_create(self, id, devconfig):
         """Create a new device for a domain.
 
-        @param dom:       domain id
+        @param id:       domain id
         @param devconfig: device configuration
         @return: deferred
         """
-        dom = int(dom)
-        dominfo = self.domain_get(dom)
-        if not dominfo:
-            raise XendError("invalid domain:" + str(dom))
+        dominfo = self.domain_lookup(id)
         self.refresh_schedule()
         val = dominfo.device_create(devconfig)
         self.update_domain(dominfo.id)
         return val
 
-    def domain_device_destroy(self, dom, type, idx):
+    def domain_device_destroy(self, id, type, idx):
         """Destroy a device.
 
-        @param dom:  domain id
+        @param id:  domain id
         @param type: device type
         @param idx:  device index
         """
-        dom = int(dom)
-        dominfo = self.domain_get(dom)
-        if not dominfo:
-            raise XendError("invalid domain:" + str(dom))
+        dominfo = self.domain_lookup(id)
         self.refresh_schedule()
         val = dominfo.device_destroy(type, idx)
         self.update_domain(dominfo.id)
         return val
 
-    def domain_devtype_ls(self, dom, type):
+    def domain_devtype_ls(self, id, type):
         """Get list of device indexes for a domain.
 
-        @param dom:  domain
+        @param id:  domain
         @param type: device type
         @return: device indexes
         """
-        dominfo = self.domain_get(dom)
-        if not dominfo: return None
+        dominfo = self.domain_lookup(id)
         devs = dominfo.get_devices(type)
-        return range(0, len(devs))
+        #return range(0, len(devs))
+        return devs
 
-    def domain_devtype_get(self, dom, type, idx):
+    def domain_devtype_get(self, id, type, idx):
         """Get a device from a domain.
 
-        @param dom:  domain
+        @param id:  domain
         @param type: device type
         @param idx:  device index
         @return: device object (or None)
         """
-        dominfo = self.domain_get(dom)
-        if not dominfo: return None
+        dominfo = self.domain_lookup(id)
         return dominfo.get_device_by_index(type, idx)
 
-    def domain_vif_ls(self, dom):
+    def domain_vif_ls(self, id):
         """Get list of virtual network interface (vif) indexes for a domain.
 
-        @param dom: domain
+        @param id: domain
         @return: vif indexes
         """
-        return self.domain_devtype_ls(dom, 'vif')
+        return self.domain_devtype_ls(id, 'vif')
 
-    def domain_vif_get(self, dom, vif):
+    def domain_vif_get(self, id, vif):
         """Get a virtual network interface (vif) from a domain.
 
-        @param dom: domain
+        @param id: domain
         @param vif: vif index
         @return: vif device object (or None)
         """
-        return self.domain_devtype_get(dom, 'vif', vif)
+        return self.domain_devtype_get(id, 'vif', vif)
 
-    def domain_vbd_ls(self, dom):
+    def domain_vbd_ls(self, id):
         """Get list of virtual block device (vbd) indexes for a domain.
 
-        @param dom: domain
+        @param id: domain
         @return: vbd indexes
         """
-        return self.domain_devtype_ls(dom, 'vbd')
+        return self.domain_devtype_ls(id, 'vbd')
 
-    def domain_vbd_get(self, dom, vbd):
+    def domain_vbd_get(self, id, vbd):
         """Get a virtual block device (vbd) from a domain.
 
-        @param dom: domain
+        @param id: domain
         @param vbd: vbd index
         @return: vbd device (or None)
         """
-        return self.domain_devtype_get(dom, 'vbd', vbd)
+        return self.domain_devtype_get(id, 'vbd', vbd)
 
-    def domain_shadow_control(self, dom, op):
+    def domain_shadow_control(self, id, op):
         """Shadow page control.
 
-        @param dom: domain
+        @param id: domain
         @param op:  operation
         """
-        dom = int(dom)
-        return xc.shadow_control(dom, op)
+        dominfo = self.domain_lookup(id)
+        return xc.shadow_control(dominfo.dom, op)
 
-    def domain_maxmem_set(self, dom, mem):
+    def domain_maxmem_set(self, id, mem):
         """Set the memory limit for a domain.
 
         @param dom: domain
         @param mem: memory limit (in MB)
         @return: 0 on success, -1 on error
         """
-        dom = int(dom)
+        dominfo = self.domain_lookup(id)
         maxmem = int(mem) * 1024
-        return xc.domain_setmaxmem(dom, maxmem_kb = maxmem)
+        return xc.domain_setmaxmem(dominfo.dom, maxmem_kb = maxmem)
 
 
 def instance():
index 9d7dfe325ccf216a4dba078f79ac00aae6bc7a99..1a9b74190aea3ae86a3590276d2a788c48c80f57 100644 (file)
@@ -193,8 +193,8 @@ config_handlers = {}
 def add_config_handler(name, h):
     """Add a handler for a config field.
 
-    name     field name
-    h        handler: fn(vm, config, field, index)
+    @param name:     field name
+    @param h:        handler: fn(vm, config, field, index)
     """
     config_handlers[name] = h
 
@@ -212,16 +212,15 @@ image_handlers = {}
 
 def add_image_handler(name, h):
     """Add a handler for an image type
-    name     image type
-    h        handler: fn(config, name, memory, image)
+    @param name:     image type
+    @param h:        handler: fn(config, name, memory, image)
     """
     image_handlers[name] = h
 
 def get_image_handler(name):
     """Get the handler for an image type.
-    name     image type
-
-    returns handler or None
+    @param name:     image type
+    @return: handler or None
     """
     return image_handlers.get(name)
 
@@ -233,17 +232,16 @@ device_handlers = {}
 def add_device_handler(name, h):
     """Add a handler for a device type.
 
-    name      device type
-            handler: fn(vm, dev)
+    @param name:     device type
+    @param h:        handler: fn(vm, dev)
     """
     device_handlers[name] = h
 
 def get_device_handler(name):
     """Get the handler for a device type.
 
-    name      device type
-
-    returns handler or None
+    @param name :     device type
+    @return; handler or None
     """
     return device_handlers.get(name)
 
@@ -252,10 +250,9 @@ def vm_create(config):
     If a vm has been partially created and there is an error it
     is destroyed.
 
-    config    configuration
-
-    returns Deferred
-    raises VmError for invalid configuration
+    @param config    configuration
+    @return: Deferred
+    @raise: VmError for invalid configuration
     """
     vm = XendDomainInfo()
     return vm.construct(config)
@@ -314,21 +311,27 @@ def vm_restore(src, progress=0):
     return deferred
     
 def dom_get(dom):
+    """Get info from xen for an existing domain.
+
+    @param dom: domain id
+    @return: info or None
+    """
     domlist = xc.domain_getinfo(dom=dom)
     if domlist and dom == domlist[0]['dom']:
         return domlist[0]
     return None
     
-
 def append_deferred(dlist, v):
+    """Append a value to a deferred list if it is a deferred.
+
+    @param dlist: list of deferreds
+    @param v: value to add
+    """
     if isinstance(v, defer.Deferred):
         dlist.append(v)
 
 def _vm_configure1(val, vm):
     d = vm.create_devices()
-    def cbok(x):
-        return x
-    d.addCallback(cbok)
     d.addCallback(_vm_configure2, vm)
     return d
 
@@ -348,7 +351,7 @@ class XendDomainInfo:
 
     """Minimum time between domain restarts in seconds.
     """
-    MINIMUM_RESTART_TIME = 10
+    MINIMUM_RESTART_TIME = 20
 
     def __init__(self):
         self.recreate = 0
@@ -363,6 +366,7 @@ class XendDomainInfo:
         self.cmdline = None
         self.console = None
         self.devices = {}
+        self.device_index = {}
         self.configs = []
         self.info = None
         self.ipaddrs = []
@@ -378,9 +382,13 @@ class XendDomainInfo:
         self.console_port = None
 
     def setdom(self, dom):
+        """Set the domain id.
+
+        @param dom: domain id
+        """
         self.dom = int(dom)
         self.id = str(dom)
-    
+
     def update(self, info):
         """Update with  info from xc.domain_getinfo().
         """
@@ -437,13 +445,39 @@ class XendDomainInfo:
             sxpr.append(['config', self.config])
         return sxpr
 
+    def check_name(self, name):
+        """Check if a vm name is valid. Valid names start with a non-digit
+        and contain alphabetic characters, digits, or characters in '_-.'.
+        The same name cannot be used for more than one vm at the same time.
+
+        @param name: name
+        @raise: VMerror if invalid
+        """
+        if name is None or name == '':
+            raise VmError('missing vm name')
+        if name[0] in string.digits:
+            raise VmError('invalid vm name')
+        for c in name:
+            if c in string.digits: continue
+            if c in '_-.': continue
+            if c in string.ascii_letters: continue
+            raise VmError('invalid vm name')
+        # See comment in XendDomain constructor about 'xd'.
+        if xd.domain_exists(name):
+            raise VmError('vm name clash: ' + name)
+        
     def construct(self, config):
+        """Construct the vm instance from its configuration.
+
+        @param config: configuration
+        @return: deferred
+        @raise: VmError on error
+        """
         # todo - add support for scheduling params?
         self.config = config
         try:
             self.name = sxp.child_value(config, 'name')
-            if self.name is None:
-                raise VmError('missing domain name')
+            self.check_name(self.name)
             self.memory = int(sxp.child_value(config, 'memory'))
             if self.memory is None:
                 raise VmError('missing memory size')
@@ -462,12 +496,9 @@ class XendDomainInfo:
                 raise VmError('unknown image type: ' + image_name)
             image_handler(self, image)
             deferred = self.configure()
-            def cbok(x):
-                return x
             def cberr(err):
                 self.destroy()
                 return err
-            deferred.addCallback(cbok)
             deferred.addErrback(cberr)
         except StandardError, ex:
             # Catch errors, cleanup and re-raise.
@@ -478,8 +509,10 @@ class XendDomainInfo:
     def config_devices(self, name):
         """Get a list of the 'device' nodes of a given type from the config.
 
-        name   device type
-        return list of device configs
+        @param name: device type
+        @type  name: string
+        @return: device configs
+        @rtype: list
         """
         devices = []
         for d in sxp.children(self.config, 'device'):
@@ -490,31 +523,57 @@ class XendDomainInfo:
         return devices
 
     def config_device(self, type, idx):
+        """Get a device config from the device nodes of a given type
+        from the config.
+
+        @param type: device type
+        @type  type: string
+        @param idx: index
+        @type  idx: int
+        @return config or None
+        """
         devs = self.config_devices(type)
         if 0 <= idx < len(devs):
             return devs[idx]
         else:
             return None
 
+    def next_device_index(self, type):
+        """Get the next index for a given device type.
+
+        @param type: device type
+        @type  type: string
+        @return device index
+        @rtype: int
+        """
+        idx = self.device_index.get(type, 0)
+        self.device_index[type] = idx + 1
+        return idx
+
     def add_device(self, type, dev):
         """Add a device to a virtual machine.
 
-        dev      device to add
+        @param type: device type
+        @param dev:  device to add
         """
         dl = self.devices.get(type, [])
         dl.append(dev)
         self.devices[type] = dl
 
     def get_devices(self, type):
+        """Get a list of the devices of a given type.
+
+        @param type: device type
+        @return: devices
+        """
         val = self.devices.get(type, [])
         return val
 
     def get_device_by_id(self, type, id):
         """Get the device with the given id.
 
-        id       device id
-
-        returns  device or None
+        @param id:       device id
+        @return:  device or None
         """
         dl = self.get_devices(type)
         for d in dl:
@@ -525,20 +584,20 @@ class XendDomainInfo:
     def get_device_by_index(self, type, idx):
         """Get the device with the given index.
 
-        idx       device index
-
-        returns  device or None
+        @param idx: device index
+        @return:  device or None
         """
+        idx = str(idx)
         dl = self.get_devices(type)
-        if 0 <= idx < len(dl):
-            return dl[idx]
-        else:
-            return None
+        for d in dl:
+            if d.getidx() == idx:
+                return d
+        return None
 
     def add_config(self, val):
         """Add configuration data to a virtual machine.
 
-        val      data to add
+        @param val: data to add
         """
         self.configs.append(val)
 
@@ -661,11 +720,11 @@ class XendDomainInfo:
     def create_domain(self, ostype, kernel, ramdisk, cmdline, vifs_n):
         """Create a domain. Builds the image but does not configure it.
 
-        ostype  OS type
-        kernel  kernel image
-        ramdisk kernel ramdisk
-        cmdline kernel commandline
-        vifs_n  number of network interfaces
+        @param ostype:  OS type
+        @param kernel:  kernel image
+        @param ramdisk: kernel ramdisk
+        @param cmdline: kernel commandline
+        @param vifs_n:  number of network interfaces
         """
         if not self.recreate:
             if not os.path.isfile(kernel):
@@ -685,8 +744,8 @@ class XendDomainInfo:
     def create_devices(self):
         """Create the devices for a vm.
 
-        returns Deferred
-        raises VmError for invalid devices
+        @return: Deferred
+        @raise: VmError for invalid devices
         """
         dlist = []
         devices = sxp.children(self.config, 'device')
@@ -730,16 +789,17 @@ class XendDomainInfo:
         """
         dev = self.get_device_by_index(type, idx)
         if not dev:
-            raise VmError('invalid device: %s %d' % (type, idx))
+            raise VmError('invalid device: %s %s' % (type, idx))
         devs = self.devices.get(type)
-        if 0 <= idx < len(devs):
-            del devs[idx]
-        dev_config = self.config_device(type, idx)
+        index = devs.index(dev)
+        dev_config = self.config_device(type, index)
         if dev_config:
             self.config.remove(['device', dev_config])
         dev.destroy()
 
     def configure_console(self):
+        """Configure the vm console port.
+        """
         x = sxp.child_value(self.config, 'console')
         if x:
             try:
@@ -749,12 +809,20 @@ class XendDomainInfo:
             self.console_port = port
 
     def configure_restart(self):
+        """Configure the vm restart mode.
+        """
         r = sxp.child_value(self.config, 'restart', RESTART_ONREBOOT)
         if r not in restart_modes:
             raise VmError('invalid restart mode: ' + str(r))
         self.restart_mode = r;
 
     def restart_needed(self, reason):
+        """Determine if the vm needs to be restarted when shutdown
+        for the given reason.
+
+        @param reason: shutdown reason
+        @return 1 if needs restaert, 0 otherwise
+        """
         if self.restart_mode == RESTART_NEVER:
             return 0
         if self.restart_mode == RESTART_ALWAYS:
@@ -764,12 +832,18 @@ class XendDomainInfo:
         return 0
 
     def restart_cancel(self):
+        """Cancel a vm restart.
+        """
         self.restart_state = None
 
     def restarting(self):
+        """Put the vm into restart mode.
+        """
         self.restart_state = STATE_RESTART_PENDING
 
     def restart_pending(self):
+        """Test if the vm has a pending restart.
+        """
         return self.restart_state == STATE_RESTART_PENDING
 
     def restart_check(self):
@@ -781,7 +855,7 @@ class XendDomainInfo:
         if self.restart_time is not None:
             tdelta = tnow - self.restart_time
             if tdelta < self.MINIMUM_RESTART_TIME:
-                msg = 'VM %d restarting too fast' % self.dom
+                msg = 'VM %s restarting too fast' % self.name
                 log.error(msg)
                 raise VmError(msg)
         self.restart_time = tnow
@@ -830,17 +904,17 @@ class XendDomainInfo:
         """
         if self.blkif_backend:
             d = defer.Deferred()
-            d.callback(1)
+            d.callback(self)
         else:
             d = xend.blkif_create(self.dom, recreate=self.recreate)
         d.addCallback(_vm_configure1, self)
         return d
 
     def dom_configure(self, dom):
-        """Configure a domain.
+        """Configure a vm for an existing domain.
 
-        dom    domain id
-        returns deferred
+        @param dom:    domain id
+        @return: deferred
         """
         d = dom_get(dom)
         if not d:
@@ -860,6 +934,8 @@ class XendDomainInfo:
         return deferred
 
     def configure_fields(self):
+        """Process the vm configuration fields using the registered handlers.
+        """
         dlist = []
         index = {}
         for field in sxp.children(self.config):
@@ -880,11 +956,10 @@ class XendDomainInfo:
 def vm_image_linux(vm, image):
     """Create a VM for a linux image.
 
-    name      vm name
-    memory    vm memory
-    image     image config
-
-    returns vm
+    @param name:      vm name
+    @param memory:    vm memory
+    @param image:     image config
+    @return: vm
     """
     kernel = sxp.child_value(image, "kernel")
     cmdline = ""
@@ -905,11 +980,10 @@ def vm_image_linux(vm, image):
 def vm_image_netbsd(vm, image):
     """Create a VM for a bsd image.
 
-    name      vm name
-    memory    vm memory
-    image     image config
-
-    returns vm
+    @param name:     vm name
+    @param memory:    vm memory
+    @param image:     image config
+    @return: vm
     """
     #todo: Same as for linux. Is that right? If so can unify them.
     kernel = sxp.child_value(image, "kernel")
@@ -932,13 +1006,14 @@ def vm_image_netbsd(vm, image):
 def vm_dev_vif(vm, val, index):
     """Create a virtual network interface (vif).
 
-    vm        virtual machine
-    val       vif config
-    index     vif index
+    @param vm:        virtual machine
+    @param val:       vif config
+    @param index:     vif index
+    @return: deferred
     """
     if vm.netif_backend:
         raise VmError('vif: vif in netif backend domain')
-    vif = index #todo
+    vif = vm.next_device_index('vif')
     vmac = sxp.child_value(val, "mac")
     xend.netif_create(vm.dom, recreate=vm.recreate)
     log.debug("Creating vif dom=%d vif=%d mac=%s", vm.dom, vif, str(vmac))
@@ -954,13 +1029,14 @@ def vm_dev_vif(vm, val, index):
 def vm_dev_vbd(vm, val, index):
     """Create a virtual block device (vbd).
 
-    vm        virtual machine
-    val       vbd config
-    index     vbd index
+    @param vm:        virtual machine
+    @param val:       vbd config
+    @param index:     vbd index
+    @return: deferred
     """
     if vm.blkif_backend:
         raise VmError('vbd: vbd in blkif backend domain')
-    vdev = index
+    vdev = vm.next_device_index('vif')
     uname = sxp.child_value(val, 'uname')
     if not uname:
         raise VmError('vbd: Missing uname')
@@ -978,6 +1054,8 @@ def vm_dev_vbd(vm, val, index):
     return defer
 
 def parse_pci(val):
+    """Parse a pci field.
+    """
     if isinstance(val, types.StringType):
         radix = 10
         if val.startswith('0x') or val.startswith('0X'):
@@ -988,6 +1066,13 @@ def parse_pci(val):
     return v
 
 def vm_dev_pci(vm, val, index):
+    """Add a pci device.
+
+    @param vm: virtual machine
+    @param val: device configuration
+    @param index: device index
+    @return: 0 on success
+    """
     bus = sxp.child_value(val, 'bus')
     if not bus:
         raise VmError('pci: Missing bus')
@@ -1013,78 +1098,21 @@ def vm_dev_pci(vm, val, index):
     return rc
     
 
-def vm_field_vfr(vm, config, val, index):
-    """Handle a vfr field in a config.
-
-    vm        virtual machine
-    config    vm config
-    val       vfr field
-    """
-    # Get the rules and add them.
-    # (vfr (vif (id foo) (ip x.x.x.x)) ... ) 
-    list = sxp.children(val, 'vif')
-    ipaddrs = []
-    for v in list:
-        id = sxp.child_value(v, 'id')
-        if id is None:
-            raise VmError('vfr: missing vif id')
-        id = int(id)
-        dev = vm.get_device_by_index('vif', id)
-        if not dev:
-            raise VmError('vfr: invalid vif id %d' % id)
-        vif = sxp.child_value(dev, 'vif')
-        ip = sxp.child_value(v, 'ip')
-        if not ip:
-            raise VmError('vfr: missing ip address')
-        ipaddrs.append(ip);
-        # todo: Configure the ipaddrs.
-    vm.ipaddrs = ipaddrs
-
-def vnet_bridge(vnet, vmac, dom, idx):
-    """Add the device for the vif to the bridge for its vnet.
-    """
-    vif = "vif%d.%d" % (dom, idx)
-    try:
-        cmd = "(vif.conn (vif %s) (vnet %s) (vmac %s))" % (vif, vnet, vmac)
-        log.debug("vnet_bridge> %s", cmd)
-        out = file("/proc/vnet/policy", "wb")
-        out.write(cmd)
-        err = out.close()
-        log.debug("vnet_bridge> err=%d", err)
-    except IOError, ex:
-        log.exception("vnet_bridge>")
-    
-def vm_field_vnet(vm, config, val, index):
-    """Handle a vnet field in a config.
+def vm_field_ignore(vm, config, val, index):
+    """Dummy config field handler used for fields with built-in handling.
 
-    vm        virtual machine
-    config    vm config
-    val       vnet field
-    index     index
+    @param vm:        virtual machine
+    @param config:    vm config
+    @param val:       vfr field
+    @param index:     field index
     """
-    # Get the vif children. For each vif look up the vif device
-    # with the given id and configure its vnet.
-    # (vnet (vif (id foo) (vnet 2) (mac x:x:x:x:x:x)) ... )
-    vif_vnets = sxp.children(val, 'vif')
-    for v in vif_vnets:
-        id = sxp.child_value(v, 'id')
-        if id is None:
-            raise VmError('vnet: missing vif id')
-        dev = vm.get_device_by_id('vif', id)
-        #vnet = sxp.child_value(v, 'vnet', 1)
-        #mac = sxp.child_value(dev, 'mac')
-        #vif = sxp.child_value(dev, 'vif')
-        #vnet_bridge(vnet, mac, vm.dom, 0)
-        #vm.add_config([ 'vif.vnet', ['id', id], ['vnet', vnet], ['mac', mac]])
-
-def vm_field_ignore(vm, config, val, index):
     pass
 
-# Register image handlers for linux and bsd.
+# Register image handlers.
 add_image_handler('linux',  vm_image_linux)
 add_image_handler('netbsd', vm_image_netbsd)
 
-# Register device handlers for vifs and vbds.
+# Register device handlers.
 add_device_handler('vif',  vm_dev_vif)
 add_device_handler('vbd',  vm_dev_vbd)
 add_device_handler('pci',  vm_dev_pci)
@@ -1098,6 +1126,4 @@ add_config_handler('image',   vm_field_ignore)
 add_config_handler('device',  vm_field_ignore)
 add_config_handler('backend', vm_field_ignore)
 
-# Register config handlers for vfr and vnet.
-add_config_handler('vfr',  vm_field_vfr)
-add_config_handler('vnet', vm_field_vnet)
+# Register other config handlers.
index 886021ee75c1d42107c0d5bd2606bfa0da452e34..7b398a3606cefc72e0d2f9726d7db19658248092 100644 (file)
@@ -22,9 +22,9 @@ class SrvDomain(SrvDir):
 
     def op_configure(self, op, req):
         fn = FormFn(self.xd.domain_configure,
-                    [['dom', 'int'],
+                    [['dom', 'str'],
                      ['config', 'sxpr']])
-        deferred = fn(req.args, {'dom': self.dom.id})
+        deferred = fn(req.args, {'dom': self.dom.name})
         deferred.addErrback(self._op_configure_err, req)
         return deferred
 
@@ -33,35 +33,35 @@ class SrvDomain(SrvDir):
         return str(err)
         
     def op_unpause(self, op, req):
-        val = self.xd.domain_unpause(self.dom.id)
+        val = self.xd.domain_unpause(self.dom.name)
         return val
         
     def op_pause(self, op, req):
-        val = self.xd.domain_pause(self.dom.id)
+        val = self.xd.domain_pause(self.dom.name)
         return val
 
     def op_shutdown(self, op, req):
         fn = FormFn(self.xd.domain_shutdown,
-                    [['dom', 'int'],
+                    [['dom', 'str'],
                      ['reason', 'str']])
-        val = fn(req.args, {'dom': self.dom.id})
+        val = fn(req.args, {'dom': self.dom.name})
         req.setResponseCode(http.ACCEPTED)
         req.setHeader("Location", "%s/.." % req.prePathURL())
         return val
 
     def op_destroy(self, op, req):
         fn = FormFn(self.xd.domain_destroy,
-                    [['dom', 'int'],
+                    [['dom', 'str'],
                      ['reason', 'str']])
-        val = fn(req.args, {'dom': self.dom.id})
+        val = fn(req.args, {'dom': self.dom.name})
         req.setHeader("Location", "%s/.." % req.prePathURL())
         return val
 
     def op_save(self, op, req):
         fn = FormFn(self.xd.domain_save,
-                    [['dom', 'int'],
+                    [['dom', 'str'],
                      ['file', 'str']])
-        deferred = fn(req.args, {'dom': self.dom.id})
+        deferred = fn(req.args, {'dom': self.dom.name})
         deferred.addCallback(self._op_save_cb, req)
         deferred.addErrback(self._op_save_err, req)
         return deferred
@@ -75,9 +75,9 @@ class SrvDomain(SrvDir):
         
     def op_migrate(self, op, req):
         fn = FormFn(self.xd.domain_migrate,
-                    [['dom', 'int'],
+                    [['dom', 'str'],
                      ['destination', 'str']])
-        deferred = fn(req.args, {'dom': self.dom.id})
+        deferred = fn(req.args, {'dom': self.dom.name})
         print 'op_migrate>', deferred
         deferred.addCallback(self._op_migrate_cb, req)
         deferred.addErrback(self._op_migrate_err, req)
@@ -99,99 +99,85 @@ class SrvDomain(SrvDir):
         req.setResponseCode(http.BAD_REQUEST, "Error: "+ str(err))
         return str(err)
 
-    def op_device_create(self, op, req):
-        fn = FormFn(self.xd.domain_device_create,
-                    [['dom', 'int'],
-                     ['config', 'sxpr']])
-        d = fn(req.args, {'dom': self.dom.id})
-        return d
-
-    def op_device_destroy(self, op, req):
-        fn = FormFn(self.xd.domain_device_destroy,
-                    [['dom', 'int'],
-                     ['type', 'str'],
-                     ['index', 'int']])
-        val = fn(req.args, {'dom': self.dom.id})
-        return val
-                
     def op_pincpu(self, op, req):
         fn = FormFn(self.xd.domain_pincpu,
-                    [['dom', 'int'],
+                    [['dom', 'str'],
                      ['cpu', 'int']])
-        val = fn(req.args, {'dom': self.dom.id})
+        val = fn(req.args, {'dom': self.dom.name})
         return val
 
     def op_cpu_bvt_set(self, op, req):
         fn = FormFn(self.xd.domain_cpu_bvt_set,
-                    [['dom', 'int'],
+                    [['dom', 'str'],
                      ['mcuadv', 'int'],
                      ['warp', 'int'],
                      ['warpl', 'int'],
                      ['warpu', 'int']])
-        val = fn(req.args, {'dom': self.dom.id})
+        val = fn(req.args, {'dom': self.dom.name})
         return val
     
     def op_cpu_fbvt_set(self, op, req):
         fn = FormFn(self.xd.domain_cpu_fbvt_set,
-                    [['dom', 'int'],
+                    [['dom', 'str'],
                      ['mcuadv', 'int'],
                      ['warp', 'int'],
                      ['warpl', 'int'],
                      ['warpu', 'int']])
-        val = fn(req.args, {'dom': self.dom.id})
+        val = fn(req.args, {'dom': self.dom.name})
         return val
 
     def op_cpu_atropos_set(self, op, req):
         fn = FormFn(self.xd.domain_cpu_atropos_set,
-                    [['dom', 'int'],
+                    [['dom', 'str'],
                      ['period', 'int'],
                      ['slice', 'int'],
                      ['latency', 'int'],
                      ['xtratime', 'int']])
-        val = fn(req.args, {'dom': self.dom.id})
+        val = fn(req.args, {'dom': self.dom.name})
         return val
 
     def op_maxmem_set(self, op, req):
         fn = FormFn(self.xd.domain_maxmem_set,
-                    [['dom', 'int'],
+                    [['dom', 'str'],
                      ['memory', 'int']])
-        val = fn(req.args, {'dom': self.dom.id})
+        val = fn(req.args, {'dom': self.dom.name})
         return val
 
+    def op_device_create(self, op, req):
+        fn = FormFn(self.xd.domain_device_create,
+                    [['dom', 'str'],
+                     ['config', 'sxpr']])
+        d = fn(req.args, {'dom': self.dom.name})
+        return d
+
+    def op_device_destroy(self, op, req):
+        fn = FormFn(self.xd.domain_device_destroy,
+                    [['dom', 'str'],
+                     ['type', 'str'],
+                     ['idx', 'str']])
+        val = fn(req.args, {'dom': self.dom.name})
+        return val
+                
     def op_vifs(self, op, req):
-        return self.xd.domain_vif_ls(self.dom.id)
+        devs = self.xd.domain_vif_ls(self.dom.name)
+        return [ dev.sxpr() for dev in devs ]
 
     def op_vif(self, op, req):
         fn = FormFn(self.xd.domain_vif_get,
-                    [['dom', 'int'],
-                     ['vif', 'int']])
-        val = fn(req.args, {'dom': self.dom.id})
+                    [['dom', 'str'],
+                     ['vif', 'str']])
+        val = fn(req.args, {'dom': self.dom.name})
         return val
 
     def op_vbds(self, op, req):
-        return self.xd.domain_vbd_ls(self.dom.id)
+        devs = self.xd.domain_vbd_ls(self.dom.name)
+        return [ dev.sxpr() for dev in devs ]
 
     def op_vbd(self, op, req):
         fn = FormFn(self.xd.domain_vbd_get,
-                    [['dom', 'int'],
-                     ['vbd', 'int']])
-        val = fn(req.args, {'dom': self.dom.id})
-        return val
-
-    def op_vbd_add(self, op, req):
-        fn = FormFn(self.xd.domain_vbd_add,
-                    [['dom', 'int'],
-                     ['uname', 'str'],
-                     ['dev', 'str'],
-                     ['mode', 'str']])
-        val = fn(req.args, {'dom': self.dom.id})
-        return val
-
-    def op_vbd_remove(self, op, req):
-        fn = FormFn(self.xd.domain_vbd_remove,
-                    [['dom', 'int'],
-                     ['dev', 'str']])
-        val = fn(req.args, {'dom': self.dom.id})
+                    [['dom', 'str'],
+                     ['vbd', 'str']])
+        val = fn(req.args, {'dom': self.dom.name})
         return val
 
     def render_POST(self, req):
index 130072c87142e2879b14ceb1a430ccfcee03624c..cc41c78c619e2ec47439f25fefa3f50eb04851d7 100644 (file)
@@ -24,7 +24,7 @@ class SrvDomainDir(SrvDir):
 
     def domain(self, x):
         val = None
-        dom = self.xd.domain_get(x)
+        dom = self.xd.domain_lookup(x)
         if not dom:
             raise XendError('No such domain ' + str(x))
         val = SrvDomain(dom)
@@ -74,7 +74,7 @@ class SrvDomainDir(SrvDir):
     def _op_create_cb(self, dominfo, configstring, req):
         """Callback to handle deferred domain creation.
         """
-        dom = dominfo.id
+        dom = dominfo.name
         domurl = "%s/%s" % (req.prePathURL(), dom)
         req.setResponseCode(http.CREATED, "created")
         req.setHeader("Location", domurl)
@@ -112,7 +112,7 @@ class SrvDomainDir(SrvDir):
         return deferred
 
     def _op_restore_cb(self, dominfo, req):
-        dom = dominfo.id
+        dom = dominfo.name
         domurl = "%s/%s" % (req.prePathURL(), dom)
         req.setResponseCode(http.CREATED)
         req.setHeader("Location", domurl)
@@ -159,12 +159,12 @@ class SrvDomainDir(SrvDir):
             sxp.show(domains, out=req)
         else:
             domains = self.xd.domains()
-            domains.sort(lambda x, y: cmp(x.id, y.id))
+            domains.sort(lambda x, y: cmp(x.name, y.name))
             req.write('<ul>')
             for d in domains:
                req.write('<li><a href="%s%s"> Domain %s</a>'
-                         % (url, d.id, d.id))
-               req.write('name=%s' % d.name)
+                         % (url, d.name, d.name))
+               req.write('id=%s' % d.id)
                req.write('memory=%d'% d.memory)
                req.write('</li>')
             req.write('</ul>')
index b411f0ca35854783c7a0f8277fac3be89657c978..8bf9a90d12faadb4ac121c3c91cfc51d84f2fdc7 100755 (executable)
@@ -215,7 +215,7 @@ class BlkDev(controller.Dev):
     """
 
     def __init__(self, ctrl, vdev, mode, segment):
-        controller.Dev.__init__(self, ctrl)
+        controller.Dev.__init__(self,  segment['device'], ctrl)
         self.vdev = vdev
         self.mode = mode
         self.device = segment['device']
@@ -227,7 +227,11 @@ class BlkDev(controller.Dev):
         return 'w' not in self.mode
 
     def sxpr(self):
-        val = ['blkdev', ['vdev', self.vdev], ['mode', self.mode] ]
+        val = ['blkdev',
+               ['idx', self.idx],
+               ['vdev', self.vdev],
+               ['device', self.device],
+               ['mode', self.mode]]
         return val
 
     def destroy(self):
index 756a7cd64e03434bb68ba65cc4b5d72c235b04db..fdc8bfc0ac678a116f18c676fc30380dd371d45b 100755 (executable)
@@ -327,10 +327,14 @@ class Dev:
     """Abstract class for a device attached to a device controller.
     """
     
-    def __init__(self, controller):
+    def __init__(self, idx, controller):
+        self.idx = str(idx)
         self.controller = controller
         self.props = {}
 
+    def getidx(self):
+        return self.idx
+
     def setprop(self, k, v):
         self.props[k] = v
 
index ec85df8f8ee4336b1b240dcc84550deccbb7541e..cce11f621e52ddd9b3e2ba8dfc5a8cd15fde1aea 100755 (executable)
@@ -112,7 +112,7 @@ class NetDev(controller.Dev):
     """
 
     def __init__(self, ctrl, vif, config):
-        controller.Dev.__init__(self, ctrl)
+        controller.Dev.__init__(self, vif, ctrl)
         self.vif = vif
         self.evtchn = None
         self.configure(config)
@@ -140,7 +140,10 @@ class NetDev(controller.Dev):
     def sxpr(self):
         vif = str(self.vif)
         mac = self.get_mac()
-        val = ['vif', ['idx', vif], ['mac', mac]]
+        val = ['vif',
+               ['idx', self.idx],
+               ['vif', vif],
+               ['mac', mac]]
         if self.bridge:
             val.append(['bridge', self.bridge])
         if self.script:
index 143ba81ab41928095ee9e8c41d2b4e97914da82b..4fd9e9a92beae4f9d2913517e0635ea55d972814 100644 (file)
@@ -366,10 +366,11 @@ def show(sxpr, out=sys.stdout):
             show(x, out)
             i += 1
         out.write(k_list_close)
+    elif isinstance(sxpr, (types.IntType, types.FloatType)):
+        out.write(str(sxpr))
     elif isinstance(sxpr, types.StringType) and atomp(sxpr):
         out.write(sxpr)
     else:
-        #out.write("'" + str(sxpr) + "'")
         out.write(repr(str(sxpr)))
 
 def show_xml(sxpr, out=sys.stdout):
index abc07fde810ae718032131c8c2af6998d022c005..e8d79573613ce9c0e023a10fa1f8d23ddf882187 100644 (file)
@@ -402,7 +402,7 @@ def make_domain(opts, config):
     except XendError, ex:
         opts.err(str(ex))
 
-    dom = int(sxp.child_value(dominfo, 'id'))
+    dom = sxp.child_value(dominfo, 'name')
     console_info = sxp.child(dominfo, 'console')
     if console_info:
         console_port = int(sxp.child_value(console_info, 'console_port'))
@@ -411,8 +411,8 @@ def make_domain(opts, config):
     
     if server.xend_domain_unpause(dom) < 0:
         server.xend_domain_destroy(dom)
-        opts.err("Failed to unpause domain %d" % dom)
-    opts.info("Started domain %d, console on port %d"
+        opts.err("Failed to unpause domain %s" % dom)
+    opts.info("Started domain %s, console on port %d"
               % (dom, console_port))
     return (dom, console_port)
 
index 73df69d5692761714ab5ce50cf4be545730e04b4..812c8967dfb3a30dfb9ae6f4aee308d68967623b 100644 (file)
@@ -27,14 +27,10 @@ def main(argv):
         return
     if len(args) < 1: opts.err('Missing domain')
     dom = args[0]
-    try:
-        domid = int(dom)
-    except:
-        opts.err('Invalid domain: ' + dom)
     if opts.vals.reboot:
         mode = 'reboot'
     else:
         mode = 'halt'
-    server.xend_domain_destroy(domid, mode)
+    server.xend_domain_destroy(dom, mode)
     
         
index d282193c432c078af2b9fa729aafa6ed729e4dd3..0d53836c57076a42109fad6eb9eaa6abec74eb41 100644 (file)
@@ -246,10 +246,10 @@ class ProgList(Prog):
                 use_long = 1
                 
         if n == 0:
-            doms = map(int, server.xend_domains())
+            doms = server.xend_domains()
             doms.sort()
         else:
-            doms = map(int, params)
+            doms = params
             
         if use_long:
             self.long_list(doms)
@@ -257,22 +257,27 @@ class ProgList(Prog):
             self.brief_list(doms)
 
     def brief_list(self, doms):
-        print 'Dom  Name             Mem(MB)  CPU  State  Time(s)'
+        print 'Name              Id  Mem(MB)  CPU  State  Time(s)  Console'
         for dom in doms:
             info = server.xend_domain(dom)
             d = {}
-            d['dom'] = int(dom)
+            d['dom'] = int(sxp.child_value(info, 'id', '-1'))
             d['name'] = sxp.child_value(info, 'name', '??')
             d['mem'] = int(sxp.child_value(info, 'memory', '0'))
             d['cpu'] = int(sxp.child_value(info, 'cpu', '0'))
             d['state'] = sxp.child_value(info, 'state', '??')
             d['cpu_time'] = float(sxp.child_value(info, 'cpu_time', '0'))
-            print ("%(dom)-4d %(name)-16s %(mem)7d  %(cpu)3d  %(state)5s  %(cpu_time)7.1f" % d)
+            console = sxp.child(info, 'console')
+            if console:
+                d['port'] = sxp.child_value(console, 'console_port')
+            else:
+                d['port'] = ''
+            print ("%(name)-16s %(dom)3d  %(mem)7d  %(cpu)3d  %(state)5s  %(cpu_time)7.1f    %(port)4s"
+                   % d)
 
     def long_list(self, doms):
         for dom in doms:
             info = server.xend_domain(dom)
-            print '\nDomain %d' % dom
             PrettyPrint.prettyprint(info)
 
 xm.prog(ProgList)
index 926aaf27f3bee7544fca09e9181610462fdb3e5f..a36c1a6b90de743a07e2d9e791b3d60872196a7b 100644 (file)
@@ -9,6 +9,8 @@ import time
 from xen.xend.XendClient import server
 from xen.xm.opts import *
 
+DOM0 = 'Domain-0'
+
 gopts = Opts(use="""[options] [DOM]
 
 Shutdown one or more domains gracefully.
@@ -35,11 +37,9 @@ gopts.opt('reboot', short='R',
           use='Shutdown and reboot.')
 
 def shutdown(opts, doms, mode, wait):
-    def domains():
-        return [ int(a) for a in server.xend_domains() ]
-    if doms == None: doms = domains()
-    if 0 in doms:
-        doms.remove(0)
+    if doms == None: doms = server.xend_domains()
+    if DOM0 in doms:
+        doms.remove(DOM0)
     for d in doms:
         server.xend_domain_shutdown(d, mode)
     if wait:
@@ -50,7 +50,7 @@ def shutdown(opts, doms, mode, wait):
                 if d in alive: continue
                 dead.append(d)
             for d in dead:
-                opts.info("Domain %d terminated" % d)
+                opts.info("Domain %s terminated" % d)
                 doms.remove(d)
             time.sleep(1)
         opts.info("All domains terminated")
@@ -76,13 +76,8 @@ def main_all(opts, args):
 def main_dom(opts, args):
     if len(args) < 1: opts.err('Missing domain')
     dom = args[0]
-    try:
-        domid = int(dom)
-    except:
-        opts.err('Invalid domain: ' + dom)
-        
     mode = shutdown_mode(opts)  
-    shutdown(opts, [ domid ], mode, opts.vals.wait)
+    shutdown(opts, [ dom ], mode, opts.vals.wait)
     
 def main(argv):
     opts = gopts
@@ -90,7 +85,6 @@ def main(argv):
     if opts.vals.help:
         opts.usage()
         return
-    print 'shutdown.main>', len(args), args
     if opts.vals.all:
         main_all(opts, args)
     else: